package com.zerui.manager.app.accessauthdevice.executer;

import com.alibaba.cola.catchlog.CatchAndLog;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.dahuatech.icc.exception.ClientException;
import com.zerui.cola.dto.PageResponse;
import com.zerui.cola.dto.Response;
import com.zerui.cola.dto.SingleResponse;
import com.zerui.devicemanager.provider.DeviceDubboService;
import com.zerui.devicemanager.provider.cmd.DeviceNodeCmd;
import com.zerui.devicemanager.provider.cmd.DeviceNodePageCmd;
import com.zerui.devicemanager.provider.dto.DeviceDTO;
import com.zerui.devicemanager.provider.dto.DeviceInfoDTO;
import com.zerui.manager.accessauthdevice.AccessAuthDevice;
import com.zerui.manager.accessauthdevice.domainservice.AccessAuthDeviceRepository;
import com.zerui.manager.deviceTouch.DeviceTouch;
import com.zerui.manager.deviceTouch.domainservice.DeviceTouchRepository;
import com.zerui.manager.icc.conf.ICCDictFileConf;
import com.zerui.manager.icc.service.DeviceInfoService;
import com.zerui.manager.iot.conf.IOTDictRemoteConf;
import com.zerui.manager.web.enums.DeviceFromEnum;
import com.zerui.manager.web.vo.icc.DeviceInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author wh
 * @create_time 2023-09-08 13:56
 */
@Slf4j
@Component
@CatchAndLog
public class AccessAuthDeviceSyncCmdExe {
    @DubboReference
    private DeviceDubboService deviceDubboService;
    @Resource
    private DeviceInfoService deviceInfoService;

    @Value("${spring.application.name}")
    private String applicationName;
    @Resource
    private AccessAuthDeviceRepository accessAuthDeviceRepository;
    @Resource
    private DeviceTouchRepository deviceTouchRepository;
    @Resource
    private ICCDictFileConf iccDictFileConf;
    @Resource
    private IOTDictRemoteConf iotDictRemoteConf;

    public Response execute() {
        synchronized (AccessAuthDeviceSyncCmdExe.class){
            DeviceNodeCmd cmd = new DeviceNodeCmd();
            cmd.setBizUnit(applicationName);
            try {
                // 1、从IoT中读取设备信息
                SingleResponse<List<DeviceInfoDTO>> response = deviceDubboService.getDeviceInfoList(cmd);
                if (ObjectUtils.isNotEmpty(response) && CollectionUtils.isNotEmpty(response.getData())) {
                    List<DeviceInfoDTO> deviceInfoS = response.getData();
                    List<AccessAuthDevice> accessAuthDevices = deviceInfoS
                            .stream()
                            .filter(e -> e.getEnable())
                            .map(this::createAccessAuthIotDevice)
                            .collect(Collectors.toList());
                    accessAuthDeviceRepository.syncAccessAuthDevice(accessAuthDevices, DeviceFromEnum.FROM_IOT.getCode());
                    deviceTouchRepository.autoSyncTouchDevices(this.touchIoTDevices(), DeviceFromEnum.FROM_IOT.getCode());
                }
            } catch (Exception e) {
                log.error("从IoT同步门禁设备到授权设备表出错", e);
            }

            try {
                // 2、从ICC中读取设备信息
                List<DeviceInfoVO> deviceInfoVOS = deviceInfoService.getAccessControls();
                if (CollectionUtils.isNotEmpty(deviceInfoVOS)) {
                    List<AccessAuthDevice> accessAuthDevices = deviceInfoVOS
                            .stream()
                            .map(this::createAccessAuthIccDevice)
                            .collect(Collectors.toList());
                    accessAuthDeviceRepository.syncAccessAuthDevice(accessAuthDevices, DeviceFromEnum.FROM_ICC.getCode());
                    deviceTouchRepository.autoSyncTouchDevices(this.touchICCDevices(), DeviceFromEnum.FROM_ICC.getCode());
                }
            } catch (Exception e) {
                log.error("从ICC同步门禁设备到授权设备表出错", e);
            }
        }
        return Response.buildSuccess();
    }

    /**
     * 生成授权IoT门禁设备
     *
     * @param e
     * @return
     */
    private AccessAuthDevice createAccessAuthIotDevice(DeviceInfoDTO e) {
        return AccessAuthDevice.builder()
                .deviceId(e.getDeviceId())
                .deviceName(e.getDeviceName())
                .deviceCode(e.getDeviceCode())
                .deviceFrom(DeviceFromEnum.FROM_IOT.getCode())
                .type(e.getType())
                .typeName(e.getTypeName())
                .position(e.getPosition())
                .createTime(LocalDateTime.now())
                .build();
    }

    /**
     * 生成授权ICC门禁设备
     *
     * @param e
     * @return
     */
    private AccessAuthDevice createAccessAuthIccDevice(DeviceInfoVO e) {
        final String type = "ICC-DR-" + e.getDeviceCategory() + "-" + e.getDeviceType();
        return AccessAuthDevice.builder()
                .deviceId(Long.parseLong(e.getDeviceCode())) // 设备ID
                .deviceName(e.getDeviceName())
                .deviceCode(e.getDeviceCode())
                .deviceFrom(DeviceFromEnum.FROM_ICC.getCode()) // ICC
                .type(type)
                .typeName(iotDictRemoteConf.getProductName(type))
                .position(null) // ICC中的设备信息没有位置
                .createTime(LocalDateTime.now())
                .build();
    }

    // 落地IoT门禁设备
    private List<DeviceTouch> touchIoTDevices() {
        int page = 1, pageSize = 100, totalCount = 0;
        List<DeviceTouch> touchDevices = new ArrayList<>();
        DeviceNodePageCmd nodePageCmd = new DeviceNodePageCmd();
        nodePageCmd.setBizUnit(applicationName);
        nodePageCmd.setPageSize(pageSize);
        do {
            nodePageCmd.setPageIndex(page);
            PageResponse<DeviceDTO> pageResponse = deviceDubboService.getPageDevcieList(nodePageCmd);
            totalCount = pageResponse.getTotalCount();
            for (DeviceDTO dto : pageResponse.getData()) {
                touchDevices.add(DeviceTouch.ofIoTDevice(dto));
            }
            page++;
        } while ((page - 1) * pageSize < totalCount);
        return touchDevices;
    }

    // 落地ICC门禁设备
    private List<DeviceTouch> touchICCDevices() throws ClientException {
        List<DeviceTouch> touchDevices = new ArrayList<>();
        List<DeviceInfoVO> all = deviceInfoService.getAccessControls();
        for (DeviceInfoVO item : all) {
            DeviceTouch deviceTouch = DeviceTouch.ofIccDevice(item);
            deviceTouch.setDeviceManufacturer(iccDictFileConf.getManufacturerName(deviceTouch.getDeviceManufacturer()));
            deviceTouch.setProductName(iotDictRemoteConf.getProductName(deviceTouch.getProductCode()));
            touchDevices.add(deviceTouch);
        }
        return touchDevices;
    }
}
